﻿using System;
using System.Runtime.Serialization;
using System.Collections.Generic;
using System.Xml.Serialization;

namespace Dynamic.Data.Model.Query
{
    [DataContract]
    [XmlType(Namespace="DynamicMatrix")]
    public sealed class LinkEntity
    {
        private JoinOperator _joinOperator;
        private FilterExpression _linkCriteria;
        private List<LinkEntity> _linkEntities;
        private string _linkFromAttributeName;
        private string _linkFromEntityName;
        private string _linkToAttributeName;
        private string _linkToEntityName;

        public LinkEntity()
        {
            this._linkEntities = new List<LinkEntity>();
            this._linkCriteria = new FilterExpression();
        }

        public LinkEntity(string linkFromEntityName, string linkToEntityName, string linkFromAttributeName, string linkToAttributeName, JoinOperator joinOperator)
        {
            this._linkEntities = new List<LinkEntity>();
            this._linkCriteria = new FilterExpression();
            this._linkFromEntityName = linkFromEntityName;
            this._linkToEntityName = linkToEntityName;
            this._linkFromAttributeName = linkFromAttributeName;
            this._linkToAttributeName = linkToAttributeName;
            this._joinOperator = joinOperator;
        }

        public void Accept(IQueryVisitor visitor)
        {
            visitor.Visit(this);
        }

        public LinkEntity AddLink(string linkToEntityName, string linkFromAttributeName, string linkToAttributeName)
        {
            return this.InternalAddLink(linkToEntityName, linkFromAttributeName, linkToAttributeName, JoinOperator.Inner);
        }

        public LinkEntity AddLink(string linkToEntityName, string linkFromAttributeName, string linkToAttributeName, JoinOperator joinOperator)
        {
            return this.InternalAddLink(linkToEntityName, linkFromAttributeName, linkToAttributeName, joinOperator);
        }

        private LinkEntity InternalAddLink(string linkToEntityName, string linkFromAttributeName, string linkToAttributeName, JoinOperator joinOperator)
        {
            LinkEntity entity = new LinkEntity(this.LinkToEntityName, linkToEntityName, linkFromAttributeName, linkToAttributeName, joinOperator);
            this._linkEntities.Add(entity);
            return entity;
        }

        [DataMember]
        public JoinOperator JoinOperator
        {
            get
            {
                return this._joinOperator;
            }
            set
            {
                this._joinOperator = value;
            }
        }

        [DataMember]
        public FilterExpression LinkCriteria
        {
            get
            {
                return this._linkCriteria;
            }
            set
            {
                this._linkCriteria = value;
            }
        }

        [DataMember]
        [XmlArrayItem(ElementName="LinkEntity", IsNullable=false, Type=typeof(LinkEntity)), XmlArray]
        public List<LinkEntity> LinkEntities
        {
            get
            {
                return this._linkEntities;
            }
            set
            {
                this._linkEntities = value;
            }
        }

        [DataMember]
        public string LinkFromAttributeName
        {
            get
            {
                return this._linkFromAttributeName;
            }
            set
            {
                this._linkFromAttributeName = value;
            }
        }

        [DataMember]
        public string LinkFromEntityName
        {
            get
            {
                return this._linkFromEntityName;
            }
            set
            {
                this._linkFromEntityName = value;
            }
        }

        [DataMember]
        public string LinkToAttributeName
        {
            get
            {
                return this._linkToAttributeName;
            }
            set
            {
                this._linkToAttributeName = value;
            }
        }

        [DataMember]
        public string LinkToEntityName
        {
            get
            {
                return this._linkToEntityName;
            }
            set
            {
                this._linkToEntityName = value;
            }
        }
    }
}

